package com.hit.comm.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;

/**
 * 通用TCP服务端
 */
@Slf4j
public class TcpServer {

    private final String name;
    private Channel channel;
    private final Integer port;
    private final EventLoopGroup bossGroup;
    private final EventLoopGroup workerGroup;
    private final ChannelInitializer<Channel> channelInitializer;

    // 构造函数，允许传递端口和ChannelInitializer
    public TcpServer(String name,Integer port, ChannelInitializer<Channel> channelInitializer) {
        this.name = name;
        this.port = port;
        this.channelInitializer = channelInitializer;
        this.bossGroup = new NioEventLoopGroup();
        this.workerGroup = new NioEventLoopGroup();
    }

    public void bind() throws InterruptedException {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .option(ChannelOption.SO_RCVBUF, 1024 * 4)
                .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(1024, 2048, 1024 * 1024))
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childHandler(channelInitializer); // 使用传入的ChannelInitializer
        try {
            //绑定所有网卡
            ChannelFuture f = b.bind(new InetSocketAddress("0.0.0.0", port)).sync();
            log.info("[tcp-server][{}] bind {} success",name,port);
            channel = f.channel();
            // 阻塞直到服务器通道关闭
            channel.closeFuture().sync();
        } catch (Exception e) {
            log.error("[tcp-server][{}] bind {} error,{}",name,port,e.getMessage());
        } finally {
            shutdown();
        }
    }

    public void shutdown() throws InterruptedException {
        if (channel != null) {
            channel.close().sync();
        }
        bossGroup.shutdownGracefully().sync();
        workerGroup.shutdownGracefully().sync();
        log.warn("[tcp-server][{}] shutdown gracefully!",name);
    }
}